import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.BufferedReader;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.yahoo.search.SearchClient;
import com.yahoo.search.SearchException;
import com.yahoo.search.WebSearchRequest;
import com.yahoo.search.WebSearchResult;
import com.yahoo.search.WebSearchResults;

public class Client implements Runnable{
		protected Vector <Request> requestsQueue = new Vector<Request>();
		Vector<Socket> socketVector = new Vector<Socket>();
		int currentRequestPosition = 0;
		String absoluteFileName;
		String host;   // Proxy host name
		String server;
		int port;
		int numberOfConnectionsAllowed = 3;
		RequestToProxyHandlingThread [] requestHandleArr; 
		boolean checkFile = true;	
		byte[] clientData = null;
		boolean clientDataFull = false;
		boolean readyForNextUrl = false;
		int contentLength = 0; // downloaded length
		int requestLength = 0; // content length of the requested object
		boolean isHTMLRequest = false;
		Vector<Byte> htmlCode = new Vector<Byte>();
		ArrayList <String> hrefLinks = new ArrayList<String>();
		ArrayList <String> modifiedLinks = new ArrayList<String>();
		boolean moreDownloads = false;
		boolean error = false;
		
		private void reset() {
			error = false;
			isHTMLRequest = false;
			readyForNextUrl = false;
			checkFile = false;
			clientData = null;
			clientDataFull = false;
			contentLength = 0; // downloaded length
			requestLength = 0; // content length of the requested object
			socketVector.removeAllElements();
			requestHandleArr = new RequestToProxyHandlingThread [numberOfConnectionsAllowed];
		}
		
		@Override
		public void run() {
			int chunk = (requestLength / numberOfConnectionsAllowed) - 1; // bytes are 0-based index
			int lowerBytes = 0;
			int upperBytes = -1;
			
			for (;;){
				//System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RERUN START METHOD >>>>>>>>>>>>>>>>>>>>>>>");
				int i = 0;
				Socket checkFileSocket = null;
				
				reset();
				
				// Loop through links to download
				if (moreDownloads)
					if (!modifiedLinks.isEmpty()) {
						hrefLinks.remove(0);
						absoluteFileName = modifiedLinks.remove(0);
					} else
						moreDownloads = false;
				
				try {
					checkFileSocket = new Socket(host,port);
				} catch (UnknownHostException e) {
					//e.printStackTrace();
					System.err.println("Unknown host name. \nPlease check the host name again. Exit...");
					System.exit(1);
				} catch (IOException e) {
					//e.printStackTrace();
					System.err.println("Client was unable to connect to the server. \nPlease check the connection again. Exit...");
					System.exit(1);
				}
				RequestToProxyHandlingThread reqth1 = new RequestToProxyHandlingThread(checkFileSocket, this);
				ResponseFromProxyHandlingThread respth1 = new ResponseFromProxyHandlingThread(checkFileSocket,this);
				
				reqth1.setRequestType("HEAD");
				reqth1.setNeedToSendRequest(true);
			
				Thread reqt1  = new Thread(reqth1);
				Thread respt1 = new Thread(respth1);
				
				reqt1.start();
				respt1.start();
				
				for (;;){
					synchronized(this){
						try {
							wait();
							break;
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				}
				if (!error) {
				//System.err.println("Check File is done. Content Length: "+requestLength);
				
				chunk = (requestLength / numberOfConnectionsAllowed) - 1; // bytes are 0-based index
				lowerBytes = 0;
				upperBytes = -1;
				isHTMLRequest = false;
				
				// DO NOT chunk html file
				if (absoluteFileName.endsWith(".htm") || absoluteFileName.endsWith(".html")){
					//("Request for a HTML file");
					isHTMLRequest = true;
					numberOfConnectionsAllowed = 1;
				}//else {		
					for (i = 0; i < numberOfConnectionsAllowed; i++){
						try {
							socketVector.add(i, new Socket(host,port));
						} catch (UnknownHostException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
						
						RequestToProxyHandlingThread reqth = new RequestToProxyHandlingThread(socketVector.get(i), this);
						ResponseFromProxyHandlingThread respth = new ResponseFromProxyHandlingThread(socketVector.get(i),this);
						requestHandleArr[i]   = reqth;
		
						reqth.setRequestType("GET");
						
						if (!isHTMLRequest){
							lowerBytes = upperBytes + 1;
							if (i == (numberOfConnectionsAllowed - 1) ) {
								reqth.setRange("bytes="+lowerBytes+"-");
							} else {
								upperBytes = lowerBytes + chunk;
								reqth.setRange("bytes="+lowerBytes+"-"+upperBytes);
							}
						}
						
						reqth.setNeedToSendRequest(true);
						
						Thread reqt  = new Thread(reqth);
						Thread respt = new Thread(respth);
						
						reqt.start();
						respt.start();
					}
				//}
					long t1 = System.currentTimeMillis();
					for (;;){	
						// All requested data transfered?
						try {
							synchronized (this){
								wait();
							}
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					
						if (clientDataFull) {
							BufferedOutputStream outFile;
							try {
								//server = absoluteFileName.substring(0, absoluteFileName.indexOf('/', 7));
								
							    int sep = absoluteFileName.lastIndexOf("/");
							    String fileName = absoluteFileName.substring(sep + 1, absoluteFileName.length());
							    
							    System.err.println("Write to output file: "+fileName);
							    
								outFile = new BufferedOutputStream(new FileOutputStream(fileName));
								if (!isHTMLRequest || moreDownloads){
									outFile.write(clientData);
									outFile.flush();
									outFile.close();
								}else {
									String fullPath = absoluteFileName.substring(0, absoluteFileName.lastIndexOf("/"));
									
									String code = new String(clientData);
									//System.err.println("ClientData: "+code);
									hrefLinks = getHrefLinks(code);
									modifiedLinks = new ArrayList<String>();
									
									for (int j=0; j<hrefLinks.size(); j++){
										String link = hrefLinks.get(j);
										
										if (!link.startsWith("http") && !link.startsWith("www")){
											
											int index = link.indexOf('/');
											// ex: Banner.html or Banner/file.html
											if (index == -1)
												modifiedLinks.add(fullPath+"/"+link.substring(0,link.length()));
											// ex: ./Banner.html or ./Banner/file.html
											else if (index == 1)
												modifiedLinks.add(fullPath+link.substring(1,link.length()));
											// ex: /Banner.html or /Banner/file.html
											else if (index == 0) 
												modifiedLinks.add(fullPath+link);
											else 
												modifiedLinks.add(fullPath+"/"+link);
											
										}
									}
									if (modifiedLinks.size() > 0)
										moreDownloads = true;
									else 
										moreDownloads = false;
									
									//for (int j=0; j<modifiedLinks.size(); j++)
									//	System.err.println("Modified link: "+modifiedLinks.get(j));
									
									for (int j=0; j<hrefLinks.size(); j++){
										String link = hrefLinks.get(j);
										if (link.startsWith("http") || link.startsWith("www")){
											hrefLinks.remove(j);
										}
									}
									//("links = "+hrefLinks.size()+" modified = "+modifiedLinks.size());
									
									//System.err.println(code);
									
									for (int j=0; j<hrefLinks.size(); j++){
										String link = hrefLinks.get(j);
										int ind = link.lastIndexOf("/");
										//System.err.println(Matcher.quoteReplacement(link)+" replaced by "+ link.substring(ind + 1, link.length()));
										code = code.replaceAll(Matcher.quoteReplacement(link), link.substring(ind + 1, link.length()));
									}
                                    String keyword = code.substring(code.indexOf("<title>")+7,code.indexOf("</title>"));
                                    System.err.println("Keyword is :"+keyword);
                                    
                                    ///////////// TESTING PURPOSE ////////////
		                            // Create the search client. Pass it your application ID.
		                            SearchClient client = new SearchClient("0ZtxQdTV34FEpRTsBvjYxLB7Gm2qNg0ANOj2Y01SYsfdao4AxTjOQtCkooHEuCQYEsrH");
		
		                            // Create the web search request. In this case we're searching for
		                            // java-related hits.
		                            WebSearchRequest request = new WebSearchRequest(keyword);
		
		                            try {
		                                // Execute the search.
		                                WebSearchResults results = client.webSearch(request);
		
		                                // Print out how many hits were found.
		                                System.out.println("Found " + results.getTotalResultsAvailable() +
		                                        " hits for java! Displaying the first " +
		                                        results.getTotalResultsReturned() + ".");
		
		                                // Iterate over the results.
		                                String resultStr ="<p><b>Advertisements by SuperProxyServer</b></p>You might be interested in these:</br>";
		                                for (int l = 0; l < results.listResults().length; l++) {
		                                    WebSearchResult result = results.listResults()[l];
		
		                                    // Print out the document title and URL.
		                                    resultStr += ("<a href=\"" + result.getUrl()+"\">"+result.getTitle()+"</a><br/>") + "\n";
		                                }
		                                
		                                
		                                code += new String(resultStr.getBytes(),0,500);
		                                code += "...";
		                                
		                            }
		                            catch (IOException e) {
		                                // Most likely a network exception of some sort.
		                                System.err.println("Error calling Yahoo! Search Service: " +
		                                        e.toString());
		                                e.printStackTrace(System.err);
		                            }
		                            catch (SearchException e) {
		                                // An issue with the XML or with the service.
		                                System.err.println("Error calling Yahoo! Search Service: " +
		                                        e.toString());
		                                e.printStackTrace(System.err);
		                            }
		                                    
                                    /////////////////////////////////////////
									
									outFile.write(code.getBytes());
									outFile.flush();
									outFile.close();
									
									numberOfConnectionsAllowed = 3;
								}
								//System.err.println("ClientData: "+new String(clientData));
								long t2 = System.currentTimeMillis();
								System.err.println("Dowload completed in "+((t2-t1)) + " ms");
							} catch (FileNotFoundException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							
							break;
						}
					}
				
					// close all socket connections after done transfer
					for (i = 0; i<socketVector.size(); i++){
						try {
							Socket soc = socketVector.get(i);
							if (!soc.isClosed())
								soc.close();
							
							synchronized (requestHandleArr[i]){
								requestHandleArr[i].notify();
							}
							
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
					if (!moreDownloads)
						synchronized(this){
							try {
								//System.err.println("XXXXXXXXXXXXX Client is waiting for next url XXXXXXXXXXXXXX");
								error = false;
								readyForNextUrl = true;
								wait();
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
				//}
				
			}

		}	
		
		ArrayList<String> getHrefLinks(String code){
			
			/**
			 * @author burhan for regexLinks
			 */
		    String regexLinks = "<a\\s[^>]*href\\s*=\\s*[\"\']?([^\"\' ]*)[\"\']?[^>]*>(.*)</a>";
	        Pattern p = Pattern.compile(regexLinks);
	        Matcher m = p.matcher(code);

	        String link = null;
	        ArrayList<String> strArr= new ArrayList<String>();
	        
	        while (m.find()) {
	            link = m.group(1);
	            strArr.add(link);
	            //System.err.println("Link: "+link);
	        }
	        
	        // Get image links
		    regexLinks = "<img\\s[^>]*src\\s*=\\s*[\"\']?([^\"\' ]*)[\"\']?[^>]*>";
	        p = Pattern.compile(regexLinks);
	        m = p.matcher(code);

	        link = null;
	        
	        while (m.find()) {
	            link = m.group(1);
	            strArr.add(link);
	            //System.err.println("Img: "+link);
	        }

	        // Get frame links
		    regexLinks = "<frame\\s[^>]*src\\s*=\\s*[\"\']?([^\"\' ]*)[\"\']?[^>]*>";
	        p = Pattern.compile(regexLinks);
	        m = p.matcher(code);

	        link = null;
	        
	        while (m.find()) {
	            link = m.group(1);
	            strArr.add(link);
	            //System.err.println("Frame: "+link);
	        }
	        
			return strArr;
		}
		
		String getRangeString(int lowerByte, int higherByte){
			return "Bytes="+lowerByte+"-"+higherByte;
		}
		
		void setNumberOfConnectionsAllowed(int num){
			numberOfConnectionsAllowed = num;
		}
		
		
		void setHost(String _host){
			host = _host;
		}
		
		void setAbsoluteFileName(String _fileName){
			absoluteFileName = _fileName;
		}
		
		public boolean isClientDataFull() {
			return clientDataFull;
		}
		public void setClientDataFull(boolean value){
			clientDataFull = false;
		}
		public boolean isReadyForNextUrl(){
			return readyForNextUrl;
		}
		public void setReadyForNextUrl(boolean rfn){
			readyForNextUrl = rfn;
		}
		public void setPort(int newPort){
			port = newPort;
		}
		public int getPort(){
		return port;
	}
		
		/**
		 * @author Tola
		 *
		 */
		class RequestToProxyHandlingThread implements Runnable{
			Request req;
			DataOutputStream outToProxy = null;
			String requestType;
			Socket socket;
			boolean needToSendRequest = false;
			String range = null;
			Client c;
			
			public RequestToProxyHandlingThread(Socket socket, Client client) {
				super();
				this.socket = socket;
				c = client;
			}
			
			public String getRange() {
				return range;
			}

			public void setRange(String range) {
				this.range = range;
			}

			
			public String getRequestType() {
				return requestType;
			}


			public void setRequestType(String requestType) {
				this.requestType = requestType;
			}			
			
			public boolean isNeedToSendRequest() {
				return needToSendRequest;
			}


			public void setNeedToSendRequest(boolean needToSendRequest) {
				this.needToSendRequest = needToSendRequest;
			}

			void transferRequest(DataOutputStream dos, String request){
				try {
					synchronized(dos){
						dos.writeBytes(request);
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			
			//TODO: add  last-modified: file.lastModified() too.
			void handleRequestToProxy(String absoluteFileName, String host, String requestType , String range) throws IOException{
				
				if (outToProxy == null)
					outToProxy = new DataOutputStream(socket.getOutputStream());
				
				String reqString = requestType+" "+absoluteFileName+" HTTP/1.1\r\nHost: "+host+"\r\n";
				
				Request reqObj = new Request();
				
				reqObj.addEntry("Host", host);
				reqObj.addEntry("File-Name", absoluteFileName);
				reqObj.addEntry("Request-Type", requestType);
				
				if (requestType.compareTo("GET") == 0){
					if (range != null) {
						if (range.compareTo("") != 0) 
							reqString += "Range: "+range+"\r\n";
						reqObj.addEntry("Range",range);
					}
				} else {
					reqString += "Connection: close\r\n";
				}
				
				reqString += "\r\n";
				
				requestsQueue.add(reqObj);	
				currentRequestPosition ++;
				transferRequest(outToProxy, reqString);

				
				/*if (checkFile){
					System.err.println("Check file info: "+absoluteFileName);
					checkFile = false;
				}*/
				
				//System.err.println("Request: "+reqString);
				
				//System.err.println("Queue: "+requestsQueue.size()+" requests.");				
				//System.err.println("==========================  End of the request =======================");
			}
			
			@Override
			public
			void run() {
				for (;;) {
					// send Head request to proxy/server for filesize before it chunks
					try {
						handleRequestToProxy(absoluteFileName,host,requestType,range);
						
						synchronized(this){
							//System.err.println("request thread waitting...");
							wait();
						}
						
						if (socket.isClosed())
							break;

					} catch (IOException e) {
						e.printStackTrace();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}			
				}
				//System.err.println("Exiting requestThread for: "+socket.getInetAddress().getHostAddress());
			}
			
			
			@SuppressWarnings("deprecation")
			String formatToGMT(long dateInMillis){
				Date date = new Date (dateInMillis);
				String GMTFormat = date.toGMTString();
				
				switch (date.getDay()){
					case 0: GMTFormat = "Sun, "+GMTFormat; break;
					case 1: GMTFormat = "Mon, "+GMTFormat; break;
					case 2: GMTFormat = "Tue, "+GMTFormat; break;
					case 3: GMTFormat = "Wed, "+GMTFormat; break;
					case 4: GMTFormat = "Thu, "+GMTFormat; break;
					case 5: GMTFormat = "Fri, "+GMTFormat; break;
					case 6: GMTFormat = "Sat, "+GMTFormat; break;
				}
		        return GMTFormat;
			}
		}

		/**
		 * @author Tola
		 *
		 */
		class ResponseFromProxyHandlingThread implements Runnable {
			DataInputStream inFromProxy;
			String responseLineMsg;
			String headerData;
			Response resp;
			boolean finishHandlingResponse = false;
			Socket socket;
			//byte [] data = null;
			//int downloaded;
			Client c;
			boolean socketClosed = false;
			
//			public byte[] getData(){
//				return data;
//			}
			
			public ResponseFromProxyHandlingThread(Socket socket, Client client) {
				super();
				this.socket = socket;
				c = client;
			}
			
			public boolean isFinishHandlingResponse() {
				return finishHandlingResponse;
			}

			public void setFinishHandlingResponse(boolean finishHandlingResponse) {
				this.finishHandlingResponse = finishHandlingResponse;
			}

			void handleResponseFromProxy() throws IOException{
				// should be create once only
				String responseLineMsg;
				try {
					if (inFromProxy == null){
						inFromProxy = new DataInputStream(socket.getInputStream());
					}
	
					//TODO problem when socket is closed after the check passed.
					responseLineMsg = inFromProxy.readLine();
				
				}catch (IOException e){
					socketClosed = true;
					return;
				}
				
				if (responseLineMsg != null && responseLineMsg.compareTo("") != 0){
					resp = new Response();
					
					// Read the rest of the message headers
					try {
						headerData = inFromProxy.readLine();
					}catch (IOException e){
						socketClosed = true;
						return;
					}
					while ( headerData != null
							&& !(headerData.equals("")) 
							&& !(headerData.equals("\n") )
							&& !(headerData.equals("\r"))
							&& !(headerData.equals("\r\n"))
							&& !(headerData.equals("\n\r") )) {
						resp.hashResponse(headerData);
						headerData = inFromProxy.readLine();
					}
					//////////////// watch out this /////////////////////////
					StringTokenizer tokenizedLine = new StringTokenizer(responseLineMsg);
					
					String httpVersion = tokenizedLine.nextToken();
					String responseCode = tokenizedLine.nextToken();
					
					int errorCode = Integer.parseInt(responseCode);
					
					//System.err.println("Error code = ["+errorCode+"]");

						
					//TODO: if responseCode is for authentication
					// authenticateUser();
					
					// Add request type, file name, and http version to the requests map
					resp.addEntry("HTTP", httpVersion);
					// File name can be absolute path too.
					resp.addEntry("ResponseCode", responseCode);
					
					// Add request to the request queue
					Request req = requestsQueue.get(0);
					
					if (req.getRequestHeaderValue("Request-Type").compareTo("GET") == 0){
						int length = Integer.parseInt(resp.getResponseHeaderValue("Content-Length"));
						
						long start = System.currentTimeMillis();
						handleContent(inFromProxy,resp,length);
						long end = System.currentTimeMillis();
						
						try {
							System.err.println("Downloading rate: "+ length*8/(end-start)+" Kbps" );
						} catch (ArithmeticException ex){
							System.err.println("Downloading rate: Unknown");
						}
						requestsQueue.remove(0);
						
						//System.err.println("GET response with DATA = "+(new String(data)));
					} else {
						requestsQueue.remove(0);
						
						// WHAT ABOUT NOT FOUND response?
						if (errorCode == 200){
							requestLength = Integer.parseInt(resp.getResponseHeaderValue("Content-Length"));
							clientData = new byte[requestLength];
							//System.err.println("HEAD response with length = "+requestLength);
						} else 
							error = true;
						checkFile = true;
						
						synchronized(c){
							c.notify();
						}
						
						////////////////
						socket.close();
						
						
					}
					
					
					//System.err.println("==========================  End of the response =======================");
					
					//////////////// DO NOT REMOVE THIS LINE. DIRTY HACK???? /////////////////////
					System.err.print("");
					////////////////////////////////////////////////////////////
					
					finishHandlingResponse = true;
				}
				//System.err.print(responseLineMsg);
		}
		
		@Override
		public void run() {
			for(;;){
				try {
					//TODO: why it is looping while transferring data? It is because other idle responsethreads?
					handleResponseFromProxy();
					
					if (socketClosed || socket.isClosed())
						break;
					
				} catch (SocketTimeoutException socEx){
					// send Timeout msg?
					break;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//System.err.println("Exiting responseThread for : "+socket.getInetAddress().getHostAddress() );
		}			
		
			void handleContent(DataInputStream inFromClient, Response resp, int messageLength) throws IOException {
				//String stringMessageLength = resp.getResponseHeaderValue("Content-Length");
				
				//System.err.println("Need to read: "+messageLength);

				try {
					int[] range;
					if (isHTMLRequest) {
						range = new int [2]; 
						range [0] = 0 ;
						range [1] = messageLength-1;
					} else
						range = resp.getRange();
					
					
					System.err.println("Please wait while downloading...");
					for (int i=range[0]; i<= range[1]; i++) {
						clientData[i] = (byte) inFromClient.read();
					}
					
					contentLength += messageLength;
					
					if (contentLength == requestLength){
						//System.err.println("Done tranfering data.");
						clientDataFull = true;
						
						/////////////////////////
						
						socket.close();
						
						synchronized (c){
							//System.err.println("nnnnnnnnnnnnn notify");
							c.notify();
						}
					}
					
					//System.err.println("transfered content: "+contentLength);

				} catch (IOException tt) {
					tt.printStackTrace();
				}
			}
	}
		
		private void resetNumOfConnections() {
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		    System.out.print("Enter new number of allowed connections (for a file segmentation): ");
		    String numConn = null;

		    try {
				numConn = br.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			numberOfConnectionsAllowed = Integer.parseInt(numConn);	
			//readyForNextUrl = true;
		}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String host = "localhost";
		//String host = "cse.ucsd.edu";
		boolean runStarted = false;
		boolean resetNumOfConn = false;
		
		Client client = new Client();
		client.setHost(host);
		client.setPort(1234); // Test CSE124 superProxy
		//client.setPort(80); 	// Test Apache on localhost
		
		Thread tClient = new Thread(client);
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

	    System.out.print("Enter url/file you want to download: ");
	    String url = null;

	    try {
			url = br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    while (true){
	    	if (client.isReadyForNextUrl() || resetNumOfConn) {
		    	try {
		    		client.setReadyForNextUrl(false);
		    		resetNumOfConn = false;
		    		System.out.print("Enter url/file you want to download: ");
		    		url = br.readLine();
			    } catch (IOException ioe) {
			        System.out.println("IO error trying to read your url!");
			        System.exit(1);
			    } 
		    }
		    
	    	if (url != null) 
			    if (url.compareToIgnoreCase("%connection") == 0){
			    	client.resetNumOfConnections();
			    	resetNumOfConn = true;
			    } else if (url.compareToIgnoreCase("%host") == 0) {
			    	//client.resetHost();
			    // regular URL 	
			    } else if (url.compareToIgnoreCase("%exit") == 0) {
			    	System.out.println("Thank you for using our SuperWebProxy client.");
			    	System.exit(1);
			    } else if (url != null && url.compareToIgnoreCase("") != 0){
			    	client.setAbsoluteFileName(url);
			    	if (!runStarted){
			    		tClient.start();
			    		runStarted = true;
			    	}
			    	synchronized (client){
			    		client.notify();
			    	}
			    }
		    
		    url = null;
	    }

	}
	
}